<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Mybatis学习笔记 | 后端学习记录</title><meta name="keywords" content="Mybatis"><meta name="author" content="h0ss"><meta name="copyright" content="h0ss"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="1、概述MyBatis 是一款优秀的持久层框架，它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO（Plain Old Java Objects，普通老式 Java 对象）为数据库中的记录【官方文档】。 Mybatis与其他的ORM">
<meta property="og:type" content="article">
<meta property="og:title" content="Mybatis学习笔记">
<meta property="og:url" content="https://blog.gpnusz.cn/2021/08/06/Mybatis%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/index.html">
<meta property="og:site_name" content="后端学习记录">
<meta property="og:description" content="1、概述MyBatis 是一款优秀的持久层框架，它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO（Plain Old Java Objects，普通老式 Java 对象）为数据库中的记录【官方文档】。 Mybatis与其他的ORM">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://www.hualigs.cn/image/610c1f94eb0a8.jpg">
<meta property="article:published_time" content="2021-08-05T17:13:37.000Z">
<meta property="article:modified_time" content="2022-07-28T07:11:30.336Z">
<meta property="article:author" content="h0ss">
<meta property="article:tag" content="Mybatis">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://www.hualigs.cn/image/610c1f94eb0a8.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="https://blog.gpnusz.cn/2021/08/06/Mybatis%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    jQuery: 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js',
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css'
    },
    fancybox: {
      js: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js',
      css: 'https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: false,
  isanchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = { 
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: false,
  postUpdate: '2022-07-28 15:11:30'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    })(window)</script><meta name="generator" content="Hexo 5.4.0"><link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head><body><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="author-avatar"><img class="avatar-img" src="/img/avatar.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="site-data"><div class="data-item is-center"><div class="data-item-link"><a href="/archives/"><div class="headline">文章</div><div class="length-num">51</div></a></div></div><div class="data-item is-center"><div class="data-item-link"><a href="/tags/"><div class="headline">标签</div><div class="length-num">14</div></a></div></div></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="not-top-img" id="page-header"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">后端学习记录</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav></header><main class="layout" id="content-inner"><div id="post"><div id="post-info"><h1 class="post-title">Mybatis学习笔记</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2021-08-05T17:13:37.000Z" title="发表于 2021-08-06 01:13:37">2021-08-06</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-07-28T07:11:30.336Z" title="更新于 2022-07-28 15:11:30">2022-07-28</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">10.2k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>40分钟</span></span></div></div></div><article class="post-content" id="article-container"><h2 id="1、概述"><a href="#1、概述" class="headerlink" title="1、概述"></a>1、概述</h2><p>MyBatis 是一款优秀的<strong>持久层框架</strong>，它支持<strong>自定义 SQL、存储过程以及高级映射</strong>。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过<strong>简单的 XML 或注解</strong>来配置和映射原始类型、接口和 Java POJO（Plain Old Java Objects，普通老式 Java 对象）为数据库中的记录【官方文档】。</p>
<p>Mybatis与其他的ORM框架不同，不是将对象与数据库表联系起来，而是<strong>将Java方法与SQL语句相关联</strong>。相比 Hibernate (全自动ORM框架)，Mybatis属于是半自动ORM，在Mybatis上进行SQL优化/SQL语句修改等操作会比较简单，在Hibernate上还需要转换为HQL语言。</p>
<h2 id="2、简单配置"><a href="#2、简单配置" class="headerlink" title="2、简单配置"></a>2、简单配置</h2><h3 id="1）环境准备"><a href="#1）环境准备" class="headerlink" title="1）环境准备"></a>1）环境准备</h3><p>使用maven进行依赖管理的项目中，只需要引入mybatis的坐标（以及mysql相关），这里以mybatis 3.5.7为例：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.mybatis<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">  	<span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mybatis<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">  	<span class="tag">&lt;<span class="name">version</span>&gt;</span>3.5.7<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>mysql<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>mysql-connector-java<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>5.1.47<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>为了显示清晰还可以引入log4j日志依赖，之后在类路径下添加配置文件：</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">log4j.rootLogger</span>=<span class="string">error, stdout</span></span><br><span class="line"><span class="meta">log4j.logger.top.jtszt</span>=<span class="string">TRACE</span></span><br><span class="line"><span class="meta">log4j.appender.stdout</span>=<span class="string">org.apache.log4j.ConsoleAppender</span></span><br><span class="line"><span class="meta">log4j.appender.stdout.layout</span>=<span class="string">org.apache.log4j.PatternLayout</span></span><br><span class="line"><span class="meta">log4j.appender.stdout.layout.ConversionPattern</span>=<span class="string">%5p [%t] - %m%n</span></span><br></pre></td></tr></table></figure>

<p>之后准备一个数据库表用于CRUD操作（同时写入几条测试数据）：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> DATABASE mybatis_db2;</span><br><span class="line">USE mybatis_db2;</span><br><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> t_employee2(</span><br><span class="line">	id <span class="type">INT</span> <span class="keyword">PRIMARY</span> KEY AUTO_INCREMENT,</span><br><span class="line">	ename <span class="type">VARCHAR</span>(<span class="number">50</span>),</span><br><span class="line">	gender <span class="type">INT</span>,</span><br><span class="line">	email <span class="type">VARCHAR</span>(<span class="number">50</span>),</span><br><span class="line">    content <span class="type">VARCHAR</span>(<span class="number">50</span>)</span><br><span class="line">);</span><br></pre></td></tr></table></figure>

<p>之后在项目中准备一个实体类，属性与数据库字段对应，用于封装对象。</p>
<p>以及创建一个接口类，先写一个获取全部信息的方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">EmployeeMapper</span> </span>&#123;</span><br><span class="line">	<span class="function">List&lt;Employee&gt; <span class="title">getAll</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>因为<strong>Mybatis使用了Java动态代理直接通过接口调用对应方法</strong>，因此这里只需要写接口类即可，无需写实现类。</p>
<h3 id="2）写配置"><a href="#2）写配置" class="headerlink" title="2）写配置"></a>2）写配置</h3><p>基于 MyBatis 的应用都需要一个配置文件，在其中配置 Configuration 实例，用于后续构建 <code>SqlSessionFactoryBuilder </code>。 而使用SqlSessionFactoryBuilder 可以构建出 <code>SqlSessionFactory</code> 实例，这是应用的核心。配置文件的样例在官方文档中也有给出：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">configuration</span></span></span><br><span class="line"><span class="meta">  <span class="meta-keyword">PUBLIC</span> <span class="meta-string">&quot;-//mybatis.org//DTD Config 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">  <span class="meta-string">&quot;http://mybatis.org/dtd/mybatis-3-config.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">configuration</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">environments</span> <span class="attr">default</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;JDBC&quot;</span>/&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driver&quot;</span> <span class="attr">value</span>=<span class="string">&quot;com.mysql.jdbc.Driver&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;jdbc:mysql:///mybatis_db&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">      <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">environments</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">mappers</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mapper</span> <span class="attr">resource</span>=<span class="string">&quot;mapper/firstMapper.xml&quot;</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">mappers</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">configuration</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>之后需要配置上SQL的映射文件，我们在资源目录下创建一个mapper.firstMapper.xml文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;</span></span><br><span class="line"><span class="meta">&lt;!DOCTYPE <span class="meta-keyword">mapper</span></span></span><br><span class="line"><span class="meta">        <span class="meta-keyword">PUBLIC</span> <span class="meta-string">&quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;</span></span></span><br><span class="line"><span class="meta">        <span class="meta-string">&quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;top.jtszt.mapper.EmployeeMapper&quot;</span>&gt;</span></span><br><span class="line">    </span><br><span class="line">    <span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getAll&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span>&gt;</span></span><br><span class="line">        select * from t_employee</span><br><span class="line">    <span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="3）测试"><a href="#3）测试" class="headerlink" title="3）测试"></a>3）测试</h3><p>简单的配置已经完成了，现在就可以尝试获取查询结果了，这里写一个测试去获取查询结果：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EmployeeTest</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    SqlSessionFactory sqlSessionFactory;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Before</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">initSqlSessionFactory</span><span class="params">()</span></span>&#123;</span><br><span class="line">        String resource = <span class="string">&quot;mybatis-config.xml&quot;</span>;</span><br><span class="line">        InputStream inputStream = <span class="keyword">null</span>;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            inputStream = Resources.getResourceAsStream(resource);</span><br><span class="line">        &#125; <span class="keyword">catch</span> (IOException e) &#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;<span class="keyword">finally</span> &#123;</span><br><span class="line">            <span class="keyword">if</span>(inputStream!=<span class="keyword">null</span>)&#123;</span><br><span class="line">                sqlSessionFactory = <span class="keyword">new</span> SqlSessionFactoryBuilder().build(inputStream);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Test</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">test01</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> (SqlSession session = sqlSessionFactory.openSession()) &#123;</span><br><span class="line">            EmployeeMapper mapper = session.getMapper(EmployeeMapper.class);</span><br><span class="line">            List&lt;Employee&gt; ls = mapper.getAll();</span><br><span class="line">            System.out.println(ls);</span><br><span class="line">        &#125;<span class="keyword">catch</span> (Exception e)&#123;</span><br><span class="line">            e.printStackTrace();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>首先我们会通过<code>Resources</code>类的 <code>getResourceAsStream</code> 方法将配置文件加载成输入流，之后new一个 <code>SqlSessionFactoryBuilder</code> 对象，调用其 <code>build</code> 方法并传入配置文件输入流，生成一个<code>sqlSessionFactory</code>，看这名字也清楚，它就是用来造sqlSession的，它里面有一个<code>openSession</code>方法，调用返回一个SqlSession。</p>
<h2 id="3、全局配置文件"><a href="#3、全局配置文件" class="headerlink" title="3、全局配置文件"></a>3、全局配置文件</h2><p>在Mbatis的全局配置中 <code>&lt;configuration&gt;</code> 标签下可配置多个标签，每个标签代表一个属性，并且他们的配置是有顺序的，从上至下依次为：</p>
<p>1、properties    2、settings,    3、typeAliases    4、typeHandlers    5、objectFactory    </p>
<p>6、objectWrapperFactory    7、reflectorFactory    8、plugins    9、environments    </p>
<p>10、databaseIdProvider    11、mappers</p>
<p>接下来详细介绍一些重要的标签的含义及使用。</p>
<h3 id="1）properties"><a href="#1）properties" class="headerlink" title="1）properties"></a>1）properties</h3><p>全局配置文件中 <code>properties</code> 属性的作用是定义全局配置变量，可以用它来加载外部化的 properties 配置文件。</p>
<h4 id="①全局配置变量"><a href="#①全局配置变量" class="headerlink" title="①全局配置变量"></a>①全局配置变量</h4><p>首先定义两个全局配置变量，之后就可以在配置数据源的时候使用 <code>$&#123;key&#125;</code> 进行值绑定。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">properties</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;jdbc.user&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;jdbc.password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;root&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">properties</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.user&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span></span><br><span class="line">    ...</span><br><span class="line"><span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="②加载外部配置"><a href="#②加载外部配置" class="headerlink" title="②加载外部配置"></a>②加载外部配置</h4><p>也可以使用properties来引入外部的配置文件，改变上面配置中数据源的硬编码，假设现在有一个外部配置文件为 <code>db.properties</code> ，</p>
<figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">jdbc.username</span>=<span class="string">root</span></span><br><span class="line"><span class="meta">jdbc.password</span>=<span class="string">root</span></span><br><span class="line"><span class="meta">jdbc.jdbcUrl</span>=<span class="string">jdbc:mysql:///mybatis_db</span></span><br><span class="line"><span class="meta">jdbc.driverClass</span>=<span class="string">com.mysql.jdbc.Driver</span></span><br></pre></td></tr></table></figure>

<p>使用properties配置外部配置，</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">properties</span> <span class="attr">resource</span>=<span class="string">&quot;db.properties&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>之后就可以在配置中使用 <code>$&#123;key&#125;</code> 取出对应属性的值。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;driver&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.driverClass&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.jdbcUrl&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;username&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.username&#125;&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;password&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.password&#125;&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br></pre></td></tr></table></figure>



<h3 id="2）setting"><a href="#2）setting" class="headerlink" title="2）setting"></a>2）setting</h3><p>这里的配置主要影响了Mybatis的行为，说是最重要的配置也不为过，包括缓存、延迟加载、驼峰映射等配置，所有可配置的属性在官方文档中都有列举，这里只记录几个比较重要的。</p>
<h4 id="①mapUnderscoreToCamelCase"><a href="#①mapUnderscoreToCamelCase" class="headerlink" title="①mapUnderscoreToCamelCase"></a>①mapUnderscoreToCamelCase</h4><p>设置为true之后即为开启驼峰命名规则映射，什么作用？</p>
<p>我们都知道在MySQL中字段的命名是可以使用下划线的，比如描述书名的字段可设置为 <code>book_name</code> ，而Java中的属性命名推荐是驼峰命名规则 <code>bookName</code> 。我们在使用 JDBC 进行查询的时候就可以体会到，如果正常查询该字段是无法封装到实体类中的，需要使用别名查询指定才可。</p>
<p>在Mybatis中只要我们开启了驼峰命名映射，那么Mybatis会帮我们自动封装，将字段名转换为符合Java命名规范的驼峰式命名。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 开启驼峰命名映射 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">&quot;mapUnderscoreToCamelCase&quot;</span> <span class="attr">value</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="②lazyLoadingEnabled"><a href="#②lazyLoadingEnabled" class="headerlink" title="②lazyLoadingEnabled"></a>②lazyLoadingEnabled</h4><p>设置为true即为开启延迟加载，搭配缓存可以达到提升查询效率的作用。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">&quot;lazyLoadingEnabled&quot;</span> <span class="attr">value</span>=<span class="string">&quot;true&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="③logImpl"><a href="#③logImpl" class="headerlink" title="③logImpl"></a>③logImpl</h4><p>用于设置日志提供商，不配置会自动查找，可用于多日志的情况下日志的选用。比如我们这里配置的是log4j的，那么可以显式地配置。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">&quot;logImpl&quot;</span> <span class="attr">value</span>=<span class="string">&quot;LOG4J&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="3）typeAliases"><a href="#3）typeAliases" class="headerlink" title="3）typeAliases"></a>3）typeAliases</h3><p>该属性标签可用于设置多个类型别名，设置之后对于全类名可以只写类名，但是建议写全类名，比较清晰。可使用 <code>typeAliase</code> 标签对别名进行设置，其中 <code>alias</code> 属性为别名内容（不设置默认为类名） ，<code>type</code> 属性为要用别名替换的内容。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">typeAliases</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">typeAlias</span> <span class="attr">alias</span>=<span class="string">&quot;Employee&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.bean.Employee&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">typeAliases</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>也可以使用 <code>package</code> 标签进行批量别名设置， <code>name</code>属性为包名。设置之后被扫描的包中的实体类别名为类名的小驼峰形式。如果需要制定别名，可以在类上标注 <code>@Alias(&quot;xx&quot;)</code> 指定。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">package</span> <span class="attr">name</span>=<span class="string">&quot;top.jtszt.bean&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>Mybatis中别名不区分大小写。</p>
<h3 id="4）typeHandlers"><a href="#4）typeHandlers" class="headerlink" title="4）typeHandlers"></a>4）typeHandlers</h3><p>MyBatis 在设置预编译SQL语句中的参数或从结果集中取出一个值时， 都会用类型处理器将获取到的值以合适的方式转换成 Java 类型。</p>
<p>简单地说，我们在使用Mybatis的增删改查时可能有传入参数，那么传入的参数是Java类型，而到数据库中运行就要进行转换，那么这个参数传到预编译SQL之前的转换就是由类型处理器完成的。Mybatis中预提供一些类型处理器：</p>
<table>
<thead>
<tr>
<th align="left">类型处理器</th>
<th align="left">Java 类型</th>
<th align="left">JDBC 类型</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>IntegerTypeHandler</code></td>
<td align="left"><code>java.lang.Integer</code>, <code>int</code></td>
<td align="left">数据库兼容的 <code>NUMERIC</code> 或 <code>INTEGER</code></td>
</tr>
<tr>
<td align="left"><code>LongTypeHandler</code></td>
<td align="left"><code>java.lang.Long</code>, <code>long</code></td>
<td align="left">数据库兼容的 <code>NUMERIC</code> 或 <code>BIGINT</code></td>
</tr>
<tr>
<td align="left"><code>FloatTypeHandler</code></td>
<td align="left"><code>java.lang.Float</code>, <code>float</code></td>
<td align="left">数据库兼容的 <code>NUMERIC</code> 或 <code>FLOAT</code></td>
</tr>
<tr>
<td align="left"><code>DoubleTypeHandler</code></td>
<td align="left"><code>java.lang.Double</code>, <code>double</code></td>
<td align="left">数据库兼容的 <code>NUMERIC</code> 或 <code>DOUBLE</code></td>
</tr>
<tr>
<td align="left">…</td>
<td align="left"></td>
<td align="left"></td>
</tr>
</tbody></table>
<p>除此之外也可以自定义typeHandler ，只需要实现 <code>TypeHandler</code> 接口， 或继承 <code>BaseTypeHandler</code>类， 并且将它映射到一个 JDBC 类型。其中的实现方法类似 <code>PreparedStatement</code> 的setObject方法，对类型进行转换或者其他处理。</p>
<p>现在我们有一个Info的实体类，包括title和content两个属性，而Employee表中的信息字段为varchar，只显示content内容，因此我们以此实现类型的转换。先写一个转换器类：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MyTypeHandler</span> <span class="keyword">implements</span> <span class="title">TypeHandler</span>&lt;<span class="title">Info</span>&gt; </span>&#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">setParameter</span><span class="params">(PreparedStatement ps, <span class="keyword">int</span> i, Info info, JdbcType jdbcType)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        ps.setObject(i, info.getContent());</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Info <span class="title">getResult</span><span class="params">(ResultSet rs, String s)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        Info info = <span class="keyword">new</span> Info();</span><br><span class="line">        info.setContent(rs.getString(s));</span><br><span class="line">        <span class="keyword">return</span> info;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Info <span class="title">getResult</span><span class="params">(ResultSet rs, <span class="keyword">int</span> i)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        Info info = <span class="keyword">new</span> Info();</span><br><span class="line">        info.setContent(rs.getString(i));</span><br><span class="line">        <span class="keyword">return</span> info;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Info <span class="title">getResult</span><span class="params">(CallableStatement cs, <span class="keyword">int</span> i)</span> <span class="keyword">throws</span> SQLException </span>&#123;</span><br><span class="line">        Info info = <span class="keyword">new</span> Info();</span><br><span class="line">        info.setContent(cs.getString(i));</span><br><span class="line">        <span class="keyword">return</span> info;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>写完类型处理器类之后配置上它，这里的JavaType 指向的是Java类型，jdbcType指向的是需要转换为的jdbc类型：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">typeHandlers</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">typeHandler</span> <span class="attr">handler</span>=<span class="string">&quot;top.jtszt.handler.MyTypeHandler&quot;</span> <span class="attr">javaType</span>=<span class="string">&quot;top.jtszt.entity.Info&quot;</span> <span class="attr">jdbcType</span>=<span class="string">&quot;VARCHAR&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">typeHandlers</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这样我们再运行查询语句，就可以看见被封装好的info字段了。</p>
<h3 id="5）environments"><a href="#5）environments" class="headerlink" title="5）environments"></a>5）environments</h3><p>MyBatis 可以配置成适应多种环境，这种机制有助于将 SQL 映射应用于多种数据库之中。现实中可以将开发、测试和生产环境配上不同的配置(比如配置不同的数据库)，我们可以在创建 <code>SqlSessionFactory</code> 的时候指定环境，如果不指定则为默认。 在配置文件中可以配置多个环境，但默认的只能有一个。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">environments</span> <span class="attr">default</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;development&quot;</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;JDBC&quot;</span>/&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;jdbc.url&#125;&quot;</span>/&gt;</span></span><br><span class="line">               ...</span><br><span class="line">           <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;<span class="name">environment</span> <span class="attr">id</span>=<span class="string">&quot;production&quot;</span>&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">transactionManager</span> <span class="attr">type</span>=<span class="string">&quot;JDBC&quot;</span>/&gt;</span></span><br><span class="line">           <span class="tag">&lt;<span class="name">dataSource</span> <span class="attr">type</span>=<span class="string">&quot;POOLED&quot;</span>&gt;</span></span><br><span class="line">               <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;url&quot;</span> <span class="attr">value</span>=<span class="string">&quot;$&#123;prod.url&#125;&quot;</span>/&gt;</span></span><br><span class="line">               ...</span><br><span class="line">           <span class="tag">&lt;/<span class="name">dataSource</span>&gt;</span></span><br><span class="line">       <span class="tag">&lt;/<span class="name">environment</span>&gt;</span></span><br><span class="line">   <span class="tag">&lt;/<span class="name">environments</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="①transactionManager"><a href="#①transactionManager" class="headerlink" title="①transactionManager"></a>①transactionManager</h4><p>这里还涉及到 <code>environment</code> 中的一个子标签 <code>&lt;transactionManager&gt;</code> ，这个标签可以指定使用的事务管理器。在 MyBatis 中有两种类型的事务管理器（JDBC、MANAGED），JDBC没什么好说的，而配成MANAGED 则表示从不提交或回滚一个连接，而是让容器来管理事务的整个生命周期，默认情况下它会关闭连接。</p>
<h4 id="②dataSource"><a href="#②dataSource" class="headerlink" title="②dataSource"></a>②dataSource</h4><p>它配置的是数据源，可以有三种选择(UNPOOLED、POOLED、JNDI)。</p>
<p>UNPOOLED：数据源的实现会在每次请求时打开和关闭连接，也就是没有连接池；</p>
<p>POOLED：连接池方式的数据源，可以避免创建新连接的消耗；</p>
<p>JNDI：这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用。</p>
<p>而在后续使用Spring整合之后，我们会让Spring进行事务管理，因此这里可不配置数据源以及事务管理器。</p>
<h3 id="6）databaseIdProvider"><a href="#6）databaseIdProvider" class="headerlink" title="6）databaseIdProvider"></a>6）databaseIdProvider</h3><p>MyBatis 可以根据不同的数据库厂商执行不同的语句，这种多厂商的支持是基于映射语句中的 <code>databaseId</code> 属性。 MyBatis 会加载带有匹配当前数据库 <code>databaseId</code> 属性和所有不带 <code>databaseId</code> 属性的语句。 如果同时找到带有 <code>databaseId</code> 和不带 <code>databaseId</code> 的相同语句，则后者会被舍弃。</p>
<p>如果想要配置针对多厂商数据库的支持，则需要在配置文件中加入<code>databaseIdProvider</code>定义：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">databaseIdProvider</span> <span class="attr">type</span>=<span class="string">&quot;DB_VENDOR&quot;</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;MySQL&quot;</span> <span class="attr">value</span>=<span class="string">&quot;mysql&quot;</span>/&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;DB2&quot;</span> <span class="attr">value</span>=<span class="string">&quot;db2&quot;</span>/&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;Oracle&quot;</span> <span class="attr">value</span>=<span class="string">&quot;oracle&quot;</span> /&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">databaseIdProvider</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这样配置以后，只要我们在映射文件中的标签上加上 <code>databaseId</code> 属性即可。</p>
<h3 id="7）mappers"><a href="#7）mappers" class="headerlink" title="7）mappers"></a>7）mappers</h3><p>这个属性标签就是指向SQL映射文件的，下面有两个标签，<code>&lt;mapper&gt;</code> 和 <code>&lt;package&gt;</code> ，其中mapper标签的 <code>resource</code> 表示直接从类路径下取， <code>class</code> 表示从映射器接口实现类的全类名获取（如果对应映射的是一个接口，那么xml文件也应该在同个包下），<code>url</code> 表示从网络资源/磁盘路径下获取。package标签下的  <code>name</code> 表示将该包内的映射器接口实现全部注册为映射器（如果xml文件在resources目录下，那么需要在该目录下也创建一个同包名的包，将文件置于其中）。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">mappers</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mapper</span> <span class="attr">resource</span>=<span class="string">&quot;mapper/EmployeeMapper.xml&quot;</span>/&gt;</span> </span><br><span class="line">    <span class="tag">&lt;<span class="name">mapper</span> <span class="attr">class</span>=<span class="string">&quot;top.jtszt.mapper.EmployeeMapper&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">package</span> <span class="attr">name</span>=<span class="string">&quot;top.jtszt.mapper&quot;</span>/&gt;</span> </span><br><span class="line"><span class="tag">&lt;/<span class="name">mappers</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h2 id="4、SQL映射文件"><a href="#4、SQL映射文件" class="headerlink" title="4、SQL映射文件"></a>4、SQL映射文件</h2><p>在mapper文件中，最大的就是一个mapper标签，其中 <code>namespace</code>属性为命名空间，指向的是该映射文件对应的接口(对于哪个接口方法的映射/实现)。命名空间的作用是利用更长的全限定名来将不同的语句隔离开来，同时也实现了对于自定义的mapper接口的绑定。也就是说从命名空间中可以看到这个映射文件对应的接口类，并且这里的SQL语句可以依据命名空间隔离开。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">mapper</span> <span class="attr">namespace</span>=<span class="string">&quot;top.jtszt.mapper.EmployeeMapper&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">mapper</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>接下来就可以了解这里面的子标签了，首先是增删改查标签。</p>
<h3 id="1）select"><a href="#1）select" class="headerlink" title="1）select"></a>1）select</h3><p>它的作用就是对查询语句进行映射，基本形式为：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;xx&quot;</span>&gt;</span>SQL语句<span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="①标签属性"><a href="#①标签属性" class="headerlink" title="①标签属性"></a>①标签属性</h4><p>首先是这里的id，指的是“这个SQL语句是对哪个方法的实现”，它在当前命名空间必须是唯一的。</p>
<p>接下来我们重新写一个映射语句，表示 “根据id查询出员工信息”：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getById&quot;</span> <span class="attr">parameterType</span>=<span class="string">&quot;integer&quot;</span> <span class="attr">useCache</span>=<span class="string">&quot;true&quot;</span> <span class="attr">timeout</span>=<span class="string">&quot;5&quot;</span> <span class="attr">statementType</span>=<span class="string">&quot;PREPARED&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span>&gt;</span></span><br><span class="line">	select * from t_employee where id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<ul>
<li><code>parameterType</code> ：表示的是传入参数的类型，实际上这个属性不用设置，Mybatis会帮我们推断出类型；</li>
<li><code>useCache</code>：为true表示将结果保存至二级缓存中，当然它默认值就为true；</li>
<li><code>flushCache</code>：执行后本地缓存与二级缓存都会被清空</li>
<li><code>timeout</code> ：设置在抛出异常之前驱动程序等待数据库返回请求结果的秒数，默认不设置；</li>
<li><code>statementType</code> ：设置底层使用的Statement类型，默认为PREPARED代表PreparedStatement；</li>
<li><code>databaseId</code>：数据库厂商标识，这个属性就是搭配全局配置文件中的databaseIdProvider的；</li>
<li><code>resultType</code> ：设置结果集的类型，如果是返回集合，则应该填其中元素的类型；</li>
</ul>
<p>这里说到的resultType还有一个与它类似的属性 <code>resultMap</code> ，它表示对于外部 resultMap 的命名引用。而resultMap是啥？</p>
<p>现在假设我们数据库表中存在一个passwd字段，而在实体类中我们定义属性为password，这时再进行查询一定会报错，因为Mybatis无法进行自动封装了。</p>
<p>此时就可以写一个resultMap来自定义规则（resultMap为mapper的子标签）：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;myResultMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;ename&quot;</span> <span class="attr">column</span>=<span class="string">&quot;ename&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;gender&quot;</span> <span class="attr">column</span>=<span class="string">&quot;gender&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;email&quot;</span> <span class="attr">column</span>=<span class="string">&quot;email&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;info&quot;</span> <span class="attr">column</span>=<span class="string">&quot;content&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;password&quot;</span> <span class="attr">column</span>=<span class="string">&quot;passwd&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>写完自定义规则之后，再将select标签的resultType更换为resultMap，之后再查询就可：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getAll&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">    select * from t_employee</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这就是select标签中的resultMap的作用，它和resultType是互斥的。</p>
<h4 id="②传参几种情况"><a href="#②传参几种情况" class="headerlink" title="②传参几种情况"></a>②传参几种情况</h4><ol>
<li>传入的参数只有一个：取值是 <strong>#{随意写}</strong> 都可以获取成功；</li>
<li>传入的参数有多个(1)：mybatis会将参数封装到一个map中，所以要取出参数必须按照默认根据索引（0, 1, …）或者 param1, param2, … 获取。<strong>这种按照位置传参的方式不推荐</strong>，只要位置一变就嗝屁了；</li>
<li>传入的参数有多个(2)：推荐在所映射的接口对应参数前加 <code>@Param(参数名)</code>  来指定封装的key，这样在取值时就可以直接使用 <code>#&#123;参数名&#125;</code>  获取。一般多个参数可先封装到类中，再作为参数传递；</li>
<li>传入的参数是实体类：直接使用 <code>#&#123;属性名&#125;</code> 获取；</li>
<li>传入的参数是map：直接使用 <code>#&#123;key&#125;</code> 获取。</li>
</ol>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 假设一个将用户名和id传入，查询出员工信息的接口</span></span><br><span class="line"><span class="function">Employee <span class="title">getEmpByInfo</span><span class="params">(<span class="meta">@Param(&quot;id&quot;)</span>Integer id, <span class="meta">@Param(&quot;ename&quot;)</span>String ename)</span></span>;</span><br></pre></td></tr></table></figure>

<p>这里传入多个参数就是用到 <code>@Param</code>来对参数进行显式表示，之后在SQL映射文件直接获取即可。</p>
<h4 id="③-和"><a href="#③-和" class="headerlink" title="③ #{ } 和 ${ }"></a>③ #{ } 和 ${ }</h4><p>对于获取参数有两种形式，<code>$&#123;&#125;</code>不会预编译参数，只是简单拼接，因此它防不了sql注入。<code>#&#123;&#125;</code> 会预编译参数，可以防止sql注入。但是需要注意的是，如果传入的是表名以及order by后的参数值，那么必须用 <code>$&#123;&#125;</code>。此外如果是对于属性的引用那么必须写 <code>$&#123;&#125;</code> ，无论是在 SQL 还是在 if 的 test 判断中。</p>
<h3 id="2）-insert、update、delete"><a href="#2）-insert、update、delete" class="headerlink" title="2） insert、update、delete"></a>2） insert、update、delete</h3><p>这三个标签就是用来表示增删改语句映射的，先看看他们的使用。这里需要注意的是在每次完成操作之后，都需要调用SqlSession的commit方法，将更改提交到数据库中。</p>
<h4 id="①insert"><a href="#①insert" class="headerlink" title="①insert"></a>①insert</h4><p>假设现在需要插入一个员工信息，那么先写一个接口：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertEmployee</span><span class="params">(Employee employee)</span></span>;</span><br></pre></td></tr></table></figure>

<p>再写映射文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 这里只插入两个个字段 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;insertEmployee&quot;</span> <span class="attr">useGeneratedKeys</span>=<span class="string">&quot;true&quot;</span> <span class="attr">keyProperty</span>=<span class="string">&quot;id&quot;</span>&gt;</span></span><br><span class="line">    INSERT INTO </span><br><span class="line">    	t_employee</span><br><span class="line">    SET </span><br><span class="line">    	ename=#&#123;ename&#125;,</span><br><span class="line">    	email=#&#123;email&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这里使用到的属性后面会分析，只需要清楚这里是实现插入功能即可。</p>
<h4 id="②update"><a href="#②update" class="headerlink" title="②update"></a>②update</h4><p>同样写接口：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">updateEmployee</span><span class="params">(Employee employee)</span></span>;</span><br></pre></td></tr></table></figure>

<p>接着写映射文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateEmployee&quot;</span>&gt;</span></span><br><span class="line">    UPDATE</span><br><span class="line">    	t_employee</span><br><span class="line">    SET</span><br><span class="line">    	ename=#&#123;ename&#125;</span><br><span class="line">    WHERE</span><br><span class="line">    	id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="③delete"><a href="#③delete" class="headerlink" title="③delete"></a>③delete</h4><p>写接口：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">deleteEmployee</span><span class="params">(Integer id)</span></span>;</span><br></pre></td></tr></table></figure>

<p>写映射文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">delete</span> <span class="attr">id</span>=<span class="string">&quot;deleteEmployee&quot;</span>&gt;</span></span><br><span class="line">    DELETE FROM</span><br><span class="line">    	t_employee</span><br><span class="line">    WHERE</span><br><span class="line">    	id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">delete</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="④属性分析"><a href="#④属性分析" class="headerlink" title="④属性分析"></a>④属性分析</h4><p>由于他们的标签体中的属性大都相同，这里也就归并到一起说，并且只写出与select标签中不一致的属性，相同的就略过了。</p>
<ul>
<li><code>flushCache</code>：同样是清缓存，不同的是对于这三个标签，它默认为true，而select为false；</li>
<li><code>useGeneratedKeys</code>：当设置为true时MyBatis会调用<code>getGeneratedKeys</code> 方法取出由数据库内部生成的主键（如自增id），默认值：false；</li>
<li><code>keyProperty</code>：用于在insert、update语句中指定主键，MyBatis可以使用getGeneratedKeys的返回值或insert语句的selectKey子元素设置它的值；</li>
<li><code>keyColumn</code>：用于在insert、update语句中指定主键列，在PostgreSQL等数据库中，当主键列不是表中的第一列的时候必须设置。</li>
</ul>
<p>当我们的id是主键列并且自增时，可以设置<code>useGeneratedKeys</code> 为true以及 <code>keyProperty</code> 为id，之后可以不用传入id的值，Mybatis会自动帮我们把自增后的id填充上。</p>
<p>假设我们现在要插入一个员工的信息，那么我们可以不传入id的值：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;insertEmployee&quot;</span> <span class="attr">useGeneratedKeys</span>=<span class="string">&quot;true&quot;</span> <span class="attr">keyProperty</span>=<span class="string">&quot;id&quot;</span>&gt;</span></span><br><span class="line">    INSERT INTO t_employee(ename,gender,email,content,passwd)</span><br><span class="line">    VALUES(#&#123;ename&#125;,#&#123;gender&#125;,#&#123;email&#125;,#&#123;info&#125;,#&#123;password&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>由于设置了那两个属性，这里的id也是可以自动填充的。</p>
<p>对于不支持自增id的数据库，我们也可以先对id值进行设置，之后再插入：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">insert</span> <span class="attr">id</span>=<span class="string">&quot;insertEmployee&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">selectKey</span> <span class="attr">keyProperty</span>=<span class="string">&quot;id&quot;</span> <span class="attr">resultType</span>=<span class="string">&quot;integer&quot;</span> <span class="attr">order</span>=<span class="string">&quot;BEFORE&quot;</span> &gt;</span></span><br><span class="line">    	SELECT UNIX_TIMESTAMP(NOW())</span><br><span class="line">    <span class="tag">&lt;/<span class="name">selectKey</span>&gt;</span></span><br><span class="line">    INSERT INTO t_employee(id,ename,gender,email,content,passwd)</span><br><span class="line">    VALUES(#&#123;id&#125;,#&#123;ename&#125;,#&#123;gender&#125;,#&#123;email&#125;,#&#123;info&#125;,#&#123;password&#125;)</span><br><span class="line"><span class="tag">&lt;/<span class="name">insert</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这样同样不需要手动传入id值。</p>
<h3 id="3）sql"><a href="#3）sql" class="headerlink" title="3）sql"></a>3）sql</h3><p>这个标签是为了将可重用的sql片段抽取出来，方便复用，这里将需要查询的几个字段抽离出来：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">sql</span> <span class="attr">id</span>=<span class="string">&quot;myStatement&quot;</span>&gt;</span> $&#123;col&#125;.id,$&#123;col&#125;.ename,$&#123;col&#125;.passwd <span class="tag">&lt;/<span class="name">sql</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>之后在增删改查语句中使用inclue语句引入：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getEmployeeById&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">	SELECT</span><br><span class="line">	<span class="tag">&lt;<span class="name">include</span> <span class="attr">refid</span>=<span class="string">&quot;myStatement&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">&quot;col&quot;</span> <span class="attr">value</span>=<span class="string">&quot;t_employee&quot;</span>/&gt;</span>	</span><br><span class="line">    <span class="tag">&lt;/<span class="name">include</span>&gt;</span></span><br><span class="line">	FROM t_employee WHERE id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h3 id="4）resultMap"><a href="#4）resultMap" class="headerlink" title="4）resultMap"></a>4）resultMap</h3><p>前面我们使用了这个标签去进行自定义封装，那么现在我们来仔细体会一下它的使用和作用。resultMap 标签中也有多个可用标签，他们也需要按照顺序配置(如果有的话)：</p>
<p>1、constructor    2、id    3、result    4、association    5、collection    6、discriminator</p>
<h4 id="①constructor"><a href="#①constructor" class="headerlink" title="①constructor"></a>①constructor</h4><p>这个标签用于在实例化类时，将结果注入到构造方法中。它的使用需要有带参数的构造方法，虽然POJO中不允许带有参构造方法。</p>
<p>现在假设实体类中有这样一个构造方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">(Integer id, String ename)</span> </span>&#123;</span><br><span class="line">	<span class="keyword">this</span>.id = id;</span><br><span class="line">	<span class="keyword">this</span>.ename = ename;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>我们需要在封装对象的时候利用该构造器注入值，那么就可以使用constructor标签：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">constructor</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">idArg</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span> <span class="attr">javaType</span>=<span class="string">&quot;integer&quot;</span>/&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">arg</span> <span class="attr">column</span>=<span class="string">&quot;ename&quot;</span> <span class="attr">javaType</span>=<span class="string">&quot;String&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">constructor</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>注意如果是参数为主键则使用的是idArg，column表示对应数据库字段。</p>
<p>也可以name属性搭配 <code>@Param</code> 注解对参数进行自定义：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> <span class="title">Employee</span><span class="params">(<span class="meta">@Param(&quot;id&quot;)</span> Integer id,<span class="meta">@Param(&quot;empName&quot;)</span> String ename)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">this</span>.id = id;</span><br><span class="line">    <span class="keyword">this</span>.ename = ename;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">constructor</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">idArg</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span> <span class="attr">javaType</span>=<span class="string">&quot;integer&quot;</span> <span class="attr">name</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">arg</span> <span class="attr">column</span>=<span class="string">&quot;ename&quot;</span> <span class="attr">javaType</span>=<span class="string">&quot;String&quot;</span> <span class="attr">name</span>=<span class="string">&quot;empName&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">constructor</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="②id-result"><a href="#②id-result" class="headerlink" title="②id result"></a>②id result</h4><p>id 和 result 标签都将一个列的值映射到一个简单数据类型的属性或字段(非实体类包装)，这两者的唯一不同是，id 元素对应的属性会被标记为对象的标识符，在比较对象实例时使用。通常主键映射使用的是id，其他字段映射使用result </p>
<p>现在拉取我们之前的实例，这就是它的使用方法：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;myResultMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;ename&quot;</span> <span class="attr">column</span>=<span class="string">&quot;ename&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;gender&quot;</span> <span class="attr">column</span>=<span class="string">&quot;gender&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;email&quot;</span> <span class="attr">column</span>=<span class="string">&quot;email&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;info&quot;</span> <span class="attr">column</span>=<span class="string">&quot;content&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;password&quot;</span> <span class="attr">column</span>=<span class="string">&quot;passwd&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>其中有多个可配置的属性：</p>
<p><code>property</code>：表示映射到的字段或属性，这里对应javabean中的属性名；</p>
<p><code>column</code>：表示数据库中的列名或者是别名；</p>
<p><code>javaType</code>：指定Java类型，如果映射到javabean中可以忽略此属性；</p>
<p><code>jdbcType</code>：指定JDBC类型，面向 JDBC 编程可填；</p>
<p><code>typeHandler</code>： 指定后可覆盖默认的类型处理器。</p>
<h4 id="③association"><a href="#③association" class="headerlink" title="③association"></a>③association</h4><blockquote>
<p>现在假设员工表中还有一个字段为 <code>department_id</code> ，而这个部门id是外键，对应的是部门表的id，现在我们需要将员工信息查询出来的同时，把部门信息也查询出来。</p>
</blockquote>
<p>首先新建一个部门表：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">CREATE</span> <span class="keyword">TABLE</span> t_department(</span><br><span class="line">	id <span class="type">INT</span> <span class="keyword">PRIMARY</span> KEY AUTO_INCREMENT,</span><br><span class="line">	`name` <span class="type">VARCHAR</span>(<span class="number">50</span>)</span><br><span class="line">);</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>接着修改员工表，并写一些测试数据：</p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ALTER</span> <span class="keyword">TABLE</span> t_employee</span><br><span class="line">	<span class="keyword">ADD</span> <span class="keyword">COLUMN</span> department_id <span class="type">INT</span>(<span class="number">11</span>) <span class="keyword">NULL</span> </span><br><span class="line">		AFTER passwd, </span><br><span class="line">	<span class="keyword">ADD</span> <span class="keyword">CONSTRAINT</span> fk_depid <span class="keyword">FOREIGN</span> KEY(department_id) </span><br><span class="line">		<span class="keyword">REFERENCES</span> t_department(id); </span><br></pre></td></tr></table></figure>

<p>接着我们修改实体类，添加一个部门实体类，并修改员工实体类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Department</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Employee</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String ename;</span><br><span class="line">    <span class="keyword">private</span> Integer gender;</span><br><span class="line">    <span class="keyword">private</span> String email;</span><br><span class="line">    <span class="keyword">private</span> Info info;</span><br><span class="line">    <span class="keyword">private</span> String password;</span><br><span class="line">    <span class="keyword">private</span> Department department;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>现在我们改造一下查询语句，使其可以查询出员工表和部门表的所有信息：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getAll&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">    SELECT</span><br><span class="line">    	e.*,</span><br><span class="line">    	d.id dept_id,</span><br><span class="line">    	d.name dept_name</span><br><span class="line">    FROM</span><br><span class="line">    	t_employee e</span><br><span class="line">    LEFT JOIN</span><br><span class="line">    	t_department d</span><br><span class="line">    ON</span><br><span class="line">    	e.`department_id`=d.`id`</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>此时如果要将department信息封装到employee对象中，就需要用到association:</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;myResultMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 其他配置省略 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">&quot;department&quot;</span> <span class="attr">javaType</span>=<span class="string">&quot;top.jtszt.entity.Department&quot;</span>&gt;</span></span><br><span class="line">    	<span class="tag">&lt;<span class="name">id</span> <span class="attr">column</span>=<span class="string">&quot;dept_id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">    	<span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;dept_name&quot;</span> <span class="attr">property</span>=<span class="string">&quot;name&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">association</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这里有两个属性说明一下：</p>
<ul>
<li><code>property</code>：表示映射到的结果，这里填的是employee对象的department属性；</li>
<li><code>javaType</code>：表示映射到的javabean的全类名，这里填的是department全类名；</li>
</ul>
<p>此外 <code>association</code> 标签下使用到的这两个标签和resultMap下的id和result表示的意义完全一致。</p>
<p>如果不想使用联合查询，也可以使用分步查询，执行多次sql。使用这种方法首先需要定义一个查询department的select映射，同样使用 <code>association</code> 标签：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">association</span> <span class="attr">property</span>=<span class="string">&quot;department&quot;</span> <span class="attr">select</span>=<span class="string">&quot;top.jtszt.mapper.DepartmentMapper.getDepartmentById&quot;</span> <span class="attr">column</span>=<span class="string">&quot;department_id&quot;</span>/&gt;</span></span><br></pre></td></tr></table></figure>

<p>这里的 <code>select</code> 属性指向查询部门的映射(命名空间+映射id)， <code>column</code> 属性指向employee表中的那个外键字段。这样配置以后Mybatis会将查出来的employee的department_id传入<code>getDepartmentById</code> 中，将返回的对象给department属性。</p>
<h4 id="④collection"><a href="#④collection" class="headerlink" title="④collection"></a>④collection</h4><p>对于属性中有集合类型的可以使用此标签。现在我们在部门实体类中增加一个属性，用来表示其部门下的全部员工信息：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Department</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> Integer id;</span><br><span class="line">    <span class="keyword">private</span> String name;</span><br><span class="line">    <span class="keyword">private</span> List&lt;Employee&gt; employeeList;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>现在我们想在查询部门的时候把其员工信息也查询出来，就需要用到collection标签：</p>
<p><strong>方式一：</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getDepartmentById&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;deptMap&quot;</span>&gt;</span></span><br><span class="line">        SELECT</span><br><span class="line">            e.*,</span><br><span class="line">            d.id dept_id,</span><br><span class="line">            d.name dept_name</span><br><span class="line">        FROM</span><br><span class="line">            t_employee e</span><br><span class="line">        LEFT JOIN</span><br><span class="line">            t_department d</span><br><span class="line">        ON</span><br><span class="line">            e.`department_id`=d.`id`</span><br><span class="line">        WHERE </span><br><span class="line">    		d.id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;deptMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.entity.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span> <span class="attr">column</span>=<span class="string">&quot;dept_id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;name&quot;</span> <span class="attr">column</span>=<span class="string">&quot;dept_name&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">collection</span> <span class="attr">property</span>=<span class="string">&quot;employeeList&quot;</span> <span class="attr">ofType</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">id</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">column</span>=<span class="string">&quot;ename&quot;</span> <span class="attr">property</span>=<span class="string">&quot;ename&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;gender&quot;</span> <span class="attr">column</span>=<span class="string">&quot;gender&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;email&quot;</span> <span class="attr">column</span>=<span class="string">&quot;email&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;info&quot;</span> <span class="attr">column</span>=<span class="string">&quot;content&quot;</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;password&quot;</span> <span class="attr">column</span>=<span class="string">&quot;passwd&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">collection</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>collection</code> 标签的<code>property</code> 表示映射到的属性名，<code>ofType</code> 表示集合中元素的类型，而在collection标签体内的标签就都是查询employee对象时的resultMap内容了，为了简便还可以直接使用 <code>resultMap</code> 属性引入employee的mapper中的resultMap：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;deptMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.entity.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span> <span class="attr">column</span>=<span class="string">&quot;dept_id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;name&quot;</span> <span class="attr">column</span>=<span class="string">&quot;dept_name&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">collection</span> <span class="attr">property</span>=<span class="string">&quot;employeeList&quot;</span> <span class="attr">ofType</span>=<span class="string">&quot;top.jtszt.entity.Employee&quot;</span> </span></span><br><span class="line"><span class="tag">                <span class="attr">resultMap</span>=<span class="string">&quot;top.jtszt.mapper.EmployeeMapper.myResultMap&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><strong>方式二：</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getDepartmentById&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;deptMap&quot;</span>&gt;</span></span><br><span class="line">        SELECT * FROM t_department WHERE id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getEmployeeByDeptId&quot;</span> </span></span><br><span class="line"><span class="tag">        <span class="attr">resultMap</span>=<span class="string">&quot;top.jtszt.mapper.EmployeeMapper.myResultMap&quot;</span>&gt;</span></span><br><span class="line">	SELECT * FROM t_employee WHERE department_id=#&#123;dept_id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">resultMap</span> <span class="attr">id</span>=<span class="string">&quot;deptMap&quot;</span> <span class="attr">type</span>=<span class="string">&quot;top.jtszt.entity.Department&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">id</span> <span class="attr">property</span>=<span class="string">&quot;id&quot;</span> <span class="attr">column</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">result</span> <span class="attr">property</span>=<span class="string">&quot;name&quot;</span> <span class="attr">column</span>=<span class="string">&quot;name&quot;</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">collection</span> <span class="attr">property</span>=<span class="string">&quot;employeeList&quot;</span> <span class="attr">select</span>=<span class="string">&quot;getEmployeeByDeptId&quot;</span> </span></span><br><span class="line"><span class="tag">                <span class="attr">column</span>=<span class="string">&quot;id&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">resultMap</span>&gt;</span></span><br></pre></td></tr></table></figure>

<h4 id="⑤discriminator"><a href="#⑤discriminator" class="headerlink" title="⑤discriminator"></a>⑤discriminator</h4><p>有时一个SQL可能会返回多个不同的结果集，使用鉴别器（discriminator）元素可以应对这种情况，它类似于 Java 中的 switch 语句。</p>
<h2 id="5、动态SQL"><a href="#5、动态SQL" class="headerlink" title="5、动态SQL"></a>5、动态SQL</h2><p>动态SQL就是可以根据不同条件进行SQL的拼接查询，比如现在有一个查询页面，可以按照单条件/多条件进行查询，那么后台的SQL语句就要求做到可根据传入条件数量拼接语句，这时动态SQL就很有用。实现动态SQL有几个标签：if、choose (when, otherwise) 、trim (where, set) 、foreach。</p>
<h3 id="1）if-amp-trim"><a href="#1）if-amp-trim" class="headerlink" title="1）if&amp;trim"></a>1）if&amp;trim</h3><p>假设我们现在需要从页面获取查询条件内容，之后写根据不为空的条件进行查询，那么就可以使用if和trim/where标签搭配，先看看和where的搭配。</p>
<p>先写一个接口：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">List&lt;Employee&gt; <span class="title">getEmployeeByInfo</span><span class="params">(Employee employee)</span></span>;</span><br></pre></td></tr></table></figure>

<p>再写映射文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getEmployeeByInfo&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">    SELECT * FROM t_employee</span><br><span class="line">    <span class="tag">&lt;<span class="name">where</span>&gt;</span></span><br><span class="line">    	<span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot; id != null &quot;</span>&gt;</span></span><br><span class="line">    		AND id=#&#123;id&#125;</span><br><span class="line">    	<span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot; ename != null and ename.trim()!=&#x27;&#x27; &quot;</span>&gt;</span></span><br><span class="line">        	AND ename=#&#123;ename&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 其他以此类推 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">where</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>当我们的employee对象是空的时候，可以查询出来所有结果(没有where子句)；传入几个参数就按几个参数查，可见where标签的作用是帮我们处理where子句添加以及and去除的问题。而if标签则是根据test中的条件判断标签体是否保留，test判断语句可以使用上OGNL语句。</p>
<p>接下来看看if和trim的搭配，还是同样的接口，修改以下映射文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getEmployeeByInfo&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">    SELECT * FROM t_employee</span><br><span class="line">    <span class="tag">&lt;<span class="name">trim</span> <span class="attr">prefix</span>=<span class="string">&quot;WHERE&quot;</span> <span class="attr">suffixOverrides</span>=<span class="string">&quot;AND&quot;</span>&gt;</span></span><br><span class="line">    	<span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot; id != null &quot;</span>&gt;</span></span><br><span class="line">        	id=#&#123;id&#125; AND</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot; ename != null and ename.trim()!=&#x27;&#x27; &quot;</span>&gt;</span></span><br><span class="line">        	ename=#&#123;ename&#125; AND</span><br><span class="line">        <span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">trim</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>trim标签可以有四个属性设置：<code>prefix</code> 表示在整个标签体之前加的内容； <code>suffix</code> 表示在整个标签之后加的内容；<code>prefixOverrides</code> 表示将标签体内首部的该内容去掉；<code>suffixOverrides</code> 表示将标签体内尾部的该内容去掉。</p>
<p>因此这里是代表在首部加上WHERE，而如果标签体尾部出现AND则去掉，这样也可以满足要求。</p>
<h3 id="2）choose"><a href="#2）choose" class="headerlink" title="2）choose"></a>2）choose</h3><p>这个就有点像switch…case了，其实就是实现条件的选择，我们还是假设对于员工信息的查询，但是现在需求变了，变成根据单条件查询了，哪个有就查哪个，还是借助刚才的接口，直接重新写映射文件即可。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getEmployeeByInfo&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">    SELECT * FROM t_employee</span><br><span class="line">    <span class="tag">&lt;<span class="name">choose</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">when</span> <span class="attr">test</span>=<span class="string">&quot;id!=null&quot;</span>&gt;</span></span><br><span class="line">        	WHERE id=#&#123;id&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">when</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">when</span> <span class="attr">test</span>=<span class="string">&quot;ename!=null and ename.trim()!=null&quot;</span>&gt;</span></span><br><span class="line">        	WHERE ename=#&#123;ename&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">when</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">otherwise</span>&gt;</span><span class="tag">&lt;/<span class="name">otherwise</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">choose</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p><code>when</code>即相当于case，test同样是判断条件，里面可写的内容与if的test一致；<code>otherwise</code>表示默认执行的内容，相当于default。</p>
<h3 id="3）foreach"><a href="#3）foreach" class="headerlink" title="3）foreach"></a>3）foreach</h3><p>现在需求又变了，只有id字段作为查询字段，但是它可以传入多个值，需要根据这组值查出符合条件的信息列表。实际开发中也常见，例如查询指定几个日期订单信息等。</p>
<p>如果需要遍历传入的条件时就需要用到foreach，按照这个需求，我们先写一个接口：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">List&lt;Employee&gt; <span class="title">getEmployeeByIds</span><span class="params">(<span class="meta">@Param(&quot;ids&quot;)</span>List&lt;Integer&gt; ids)</span></span>;</span><br></pre></td></tr></table></figure>

<p>这里使用<code>@Param</code> 来自定义参数名，接着写映射文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">select</span> <span class="attr">id</span>=<span class="string">&quot;getEmployeeByIds&quot;</span> <span class="attr">resultMap</span>=<span class="string">&quot;myResultMap&quot;</span>&gt;</span></span><br><span class="line">    SELECT * FROM t_employee</span><br><span class="line">    <span class="tag">&lt;<span class="name">trim</span> <span class="attr">prefix</span>=<span class="string">&quot;WHERE&quot;</span> &gt;</span></span><br><span class="line">        id IN</span><br><span class="line">        <span class="tag">&lt;<span class="name">foreach</span> <span class="attr">collection</span>=<span class="string">&quot;ids&quot;</span> <span class="attr">item</span>=<span class="string">&quot;ids_item&quot;</span> </span></span><br><span class="line"><span class="tag">                 <span class="attr">separator</span>=<span class="string">&quot;,&quot;</span> <span class="attr">open</span>=<span class="string">&quot;(&quot;</span> <span class="attr">close</span>=<span class="string">&quot;)&quot;</span>&gt;</span></span><br><span class="line">        	$&#123;ids_item&#125;</span><br><span class="line">        <span class="tag">&lt;/<span class="name">foreach</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">trim</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">select</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>这里需要注意foreach的几个属性，其中<code>collection</code> 代表的是传入的集合的参数名，我们前面使用<code>@Param</code> 指定了；<code>item</code> 配一个变量名，表示每次遍历出的值；<code>separator</code> 表示每次遍历出来的值用什么风格，由于是in语句就用了逗号；<code>open</code> 表示遍历开始前的字符；<code>close</code> 表示遍历结束的字符。</p>
<h3 id="4）set"><a href="#4）set" class="headerlink" title="4）set"></a>4）set</h3><p>在进行update操作时，使用上set标签可以减少一定的工作量。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">update</span> <span class="attr">id</span>=<span class="string">&quot;updateEmployee&quot;</span>&gt;</span></span><br><span class="line">    UPDATE t_employee</span><br><span class="line">    <span class="tag">&lt;<span class="name">set</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;ename != null&quot;</span>&gt;</span>ename=#&#123;ename&#125;,<span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">if</span> <span class="attr">test</span>=<span class="string">&quot;email != null&quot;</span>&gt;</span>email=#&#123;email&#125;,<span class="tag">&lt;/<span class="name">if</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">set</span>&gt;</span></span><br><span class="line">    WHERE id=#&#123;id&#125;</span><br><span class="line"><span class="tag">&lt;/<span class="name">update</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>在update中使用set标签，它会自动帮我们加上SET前缀，并且抹去最后一个逗号。</p>
<h2 id="6、基于注解配置"><a href="#6、基于注解配置" class="headerlink" title="6、基于注解配置"></a>6、基于注解配置</h2><p>前面使用的配置都是基于xml的配置，实际上Mybatis3之后还提供了基于注解的配置，但是这种配置方式的表达能力和灵活性十分有限，甚至可以说复杂SQL根据注解来进行配置简直是灾难，不过简单语句配置利用注解确实很方便。</p>
<p>使用注解进行配置时我们只需要保留全局配置文件即可，并提供包含查询方法定义的接口类。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">interface</span> <span class="title">EmployeeMapperByAnnotation</span> </span>&#123;</span><br><span class="line">    <span class="function">Employee <span class="title">getEmployeeById</span><span class="params">(Integer id)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">insertEmployee</span><span class="params">(Employee employee)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">deleteEmployee</span><span class="params">(Integer id)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">int</span> <span class="title">updateEmployee</span><span class="params">(Employee employee)</span></span>;</span><br><span class="line"></span><br><span class="line">    <span class="function">List&lt;Employee&gt; <span class="title">getAll</span><span class="params">()</span></span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="1）-Select"><a href="#1）-Select" class="headerlink" title="1）@Select"></a>1）@Select</h3><h4 id="①基本查询"><a href="#①基本查询" class="headerlink" title="①基本查询"></a>①基本查询</h4><p>首先是用于查询的注解 <code>@Select</code> ，先看它的用法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Select(&quot;SELECT * FROM t_employee&quot;)</span></span><br><span class="line"><span class="function">List&lt;Employee&gt; <span class="title">getAll</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>

<p>这样就相当于在mapper配置文件中写了一个<code>&lt;select&gt;</code> ，这样是可以查询出基本字段的，但实际上那些我们之前在resultMap中定义过的复杂的映射是无法完成的。</p>
<h4 id="②带参"><a href="#②带参" class="headerlink" title="②带参"></a>②带参</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Select(&quot;SELECT * FROM t_employee WHERE id=#&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="function">Employee <span class="title">getEmployeeById</span><span class="params">(Integer id)</span></span>;</span><br></pre></td></tr></table></figure>

<p>这样也可以完成根据id的查询。说到按条件查询，这里是固定条件的查询，可如果是动态SQL的编写，也就是说条件不确定的情况下，使用注解要去拼接 <code>&lt;script&gt;</code> 写成脚本的形式，这种方式太…了，这里也不写了，就提一嘴。</p>
<h4 id="③结果集映射"><a href="#③结果集映射" class="headerlink" title="③结果集映射"></a>③结果集映射</h4><p>上面我们也看到了，查询出来的有关自定义类型映射的都不能正确显示，在xml中我们使用<code>&lt;resultMap&gt;</code> 去配置，在注解中也可以进行配置：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Select(&quot;SELECT * FROM t_employee&quot;)</span></span><br><span class="line"><span class="meta">@Results(id = &quot;myMap&quot;, value = &#123;</span></span><br><span class="line"><span class="meta">    @Result(id = true, property = &quot;password&quot;, column = &quot;passwd&quot;),</span></span><br><span class="line"><span class="meta">    @Result(property = &quot;info&quot;, column = &quot;content&quot;)</span></span><br><span class="line"><span class="meta">&#125;)</span></span><br><span class="line"><span class="function">List&lt;Employee&gt; <span class="title">getAll</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>

<p>这里的 <code>@Results</code> 相当于 <code>&lt;resultMap&gt;</code> 标签，它的id属性即为对该结果集映射的标识，value相当于标签体。而<code>@Result</code> 就相当于 <code>&lt;result&gt;</code> ，当id为true时，这个注解也相当于 <code>&lt;id&gt;</code>。</p>
<p>注解配置的结果集也可以复用，我们可以使用 <code>@ResultMap</code> 注解来引用：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Select(&quot;SELECT * FROM t_employee WHERE id=#&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="meta">@ResultMap(&quot;myMap&quot;)</span></span><br><span class="line"><span class="function">Employee <span class="title">getEmployeeById</span><span class="params">(Integer id)</span></span>;</span><br></pre></td></tr></table></figure>

<p>此外还有其他的一些注解可以和xml配置中的标签对应上，但Mybatis不建议使用注解完成复杂的SQL映射编写。</p>
<h3 id="2）-Insert-、-Update、-Delete"><a href="#2）-Insert-、-Update、-Delete" class="headerlink" title="2）@Insert 、@Update、@Delete"></a>2）@Insert 、@Update、@Delete</h3><p>先针对增删改注解写一个简单的实例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//插入</span></span><br><span class="line"><span class="meta">@Insert(&quot;INSERT INTO t_employee SET ename=#&#123;ename&#125;,email=#&#123;email&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertEmployee</span><span class="params">(Employee employee)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//更新</span></span><br><span class="line"><span class="meta">@Update(&quot;UPDATE t_employee SET ename=#&#123;ename&#125;,email=#&#123;email&#125; WHERE id=#&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">updateEmployee</span><span class="params">(Employee employee)</span></span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">//删除</span></span><br><span class="line"><span class="meta">@Delete(&quot;DELETE FROM t_employee WHERE id=#&#123;id&#125;&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">deleteEmployee</span><span class="params">(Integer id)</span></span>;</span><br></pre></td></tr></table></figure>

<p>之前我们还配置了id的自增，这里也可以使用，需要使用到 <code>@Options</code> 注解，这个注解可以填充大部分的属性，之后将useGeneratedKeys以及keyProperty补充上即可。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Insert(&quot;INSERT INTO t_employee SET ename=#&#123;ename&#125;,email=#&#123;email&#125;&quot;)</span></span><br><span class="line"><span class="meta">@Options(useGeneratedKeys = true, keyProperty = &quot;id&quot;)</span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertEmployee</span><span class="params">(Employee employee)</span></span>;</span><br></pre></td></tr></table></figure>

<p>这里再提一下  <code>@Options</code> 注解，里面可设置的属性实际上就等同于xml配置标签中的属性，需要使用到点进去方法查看即可。</p>
<h3 id="3）Provider系列"><a href="#3）Provider系列" class="headerlink" title="3）Provider系列"></a>3）Provider系列</h3><p>Provider 型注解允许指定返回 SQL 语句的类和方法，以供运行时执行，这类注解有两个属性：type 代表一个提供 SQL 的类，method代表一个提供 SQL 的方法，这个方法需要有一个 String 类型的返回值，参数可以根据实际情况定义。</p>
<p>使用这个注解之前，我们先准备一个Provider类，针对查询所有信息写一个方法：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">EmployeeProvider</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> String <span class="title">getAll</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>然后将EmployeeMapper接口的注解修改为@SelectProvider：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@SelectProvider(type = EmployeeProvider.class, method = &quot;getAll&quot;)</span></span><br><span class="line"><span class="function">List&lt;Employee&gt; <span class="title">getAll</span><span class="params">()</span></span>;</span><br></pre></td></tr></table></figure>

<p>这里的type指向我们自定义的Provider类，method指向对应的方法。之后就可以在getAll方法体内写内容了：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">public</span> String <span class="title">getAll</span><span class="params">()</span></span>&#123;</span><br><span class="line">    SQL sql = <span class="keyword">new</span> SQL();</span><br><span class="line">    sql.SELECT(<span class="string">&quot;*&quot;</span>).FROM(<span class="string">&quot;t_employee2&quot;</span>);</span><br><span class="line">    <span class="keyword">return</span> sql.toString();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这里直接调用了MyBatis提供的 API 构建出 SQL ，正是由于使用上了API，因而这里对于动态SQL也是可以写的，多加几个if语句然后调用AND方法以及WHERE方法等就可以实现，尽管这种方式写出来的方法后续有变动需要重新编译。此外还有InsertProvider、UpdateProvider、DeleteProvider，这些的用法都跟上面的实例差不多。</p>
<h2 id="7、缓存"><a href="#7、缓存" class="headerlink" title="7、缓存"></a>7、缓存</h2><p>Mybatis中提供了强大的事务性查询缓存机制，在这里缓存也分为一级缓存和二级缓存。</p>
<h3 id="1）一级缓存"><a href="#1）一级缓存" class="headerlink" title="1）一级缓存"></a>1）一级缓存</h3><h4 id="①基本使用"><a href="#①基本使用" class="headerlink" title="①基本使用"></a>①基本使用</h4><p>Mybatis中的一级缓存比较常用，并且它是默认开启的，一级缓存基于 <code>SqlSession</code> ，默认情况下它会自动开启事务，所以一级缓存会自动使用。</p>
<p>假设我们现在在同一个sqlSession中进行两次相同的查询，那么第二次查询是不会重新去数据库中查询的，因为第一次查询之后的结果被存储到了一级缓存中。</p>
<p><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cfa33e39f70a46b08c5187353da9079b~tplv-k3u1fbpfcp-watermark.image" alt="image-20210805180103948.png"></p>
<p>从日志我们可以看到，从第一次出结果到第二次出结果中间是不会有新的SQL查询发起的。</p>
<h4 id="②一级缓存失效"><a href="#②一级缓存失效" class="headerlink" title="②一级缓存失效"></a>②一级缓存失效</h4><p>一级缓存在遇到一些特定的情况也会失效，失效之后像上面那种情况就需要重新发SQL查询了。一级缓存失效的场景主要有：</p>
<ul>
<li>跨sqlSession：因为一级缓存本来就是基于sqlSession的，所以不同的sqlSession之间一级缓存肯定不能相通，因而也就会出现这种失效情况；</li>
<li>混入增删改：如果在两次查询之间有了增删改操作，那么一级缓存会失效，我们之前将这三个标签的flushCache属性时也看到了它默认是true；</li>
<li>调clearCache：sqlSession中有一个方法 clearCache， 调用它会清空一级缓存</li>
</ul>
<p>下图为没有一级缓存的情况：</p>
<p><img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/900c7efc81ca4381b349fce40f5c1cda~tplv-k3u1fbpfcp-watermark.image" alt="image-20210805222144376.png"></p>
<h3 id="2）二级缓存"><a href="#2）二级缓存" class="headerlink" title="2）二级缓存"></a>2）二级缓存</h3><p>二级缓存即是全局作用域的缓存，Mybatis提供二级缓存的接口和实现，缓存的实现要求实体类实现Serializable接口，并且二级缓存只有在sqlSession关闭/提交之后才会生效。</p>
<p>在Mybatis中二级缓存是默认开启的，关闭需要在全局配置文件中进行操作：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">settings</span>&gt;</span></span><br><span class="line">	<span class="tag">&lt;<span class="name">setting</span> <span class="attr">name</span>=<span class="string">&quot;cacheEnabled&quot;</span> <span class="attr">value</span>=<span class="string">&quot;false&quot;</span>/&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">settings</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>如果是xml配置则在需要使用二级缓存的mapper文件中写入cache标签，如果是基于注解配置的，就在mapper接口上标注 <code>@CacheNamespace</code>。这样即使我们使用两个不同的sqlSession执行相同的SQL，第二个也是刻意直接从缓存中取结果的。</p>
<p>这里关注一下cache标签中的几个属性：</p>
<p><code>eviction</code>：表示缓存的回收(清除)策略，默认为LRU，可选项为FIFO/SOFT/WEAK；</p>
<p><code>type</code>：缓存的实现，默认为本地缓存，整合第三方缓存时需要修改它；</p>
<p><code>size</code>：缓存引用的数量，默认1024；</p>
<p><code>flushInterval：</code>缓存定时清除时间，默认无；</p>
<p><code>readOnly</code>：设置为true则查询后返回的对象为基于序列化的深拷贝，效率会降低但安全；</p>
<p><code>blocking：</code>如果为true则当找不到对应数据时会一直阻塞直到有对应数据进来。</p>
<p>此外这里的缓存还可以整合第三方的缓存EhCache ，步骤就是导EhCache依赖，写EhCache 配置文件(官网copy即可)，修改cache标签的type属性，这样就大功告成了，这里就不细写了。</p>
<hr>
<p><em>参考资料：</em></p>
<ul>
<li><a target="_blank" rel="noopener" href="https://mybatis.org/mybatis-3/zh/">MyBatis 3.5.7官方文档</a></li>
<li><a target="_blank" rel="noopener" href="https://juejin.cn/book/6944917557878980638">玩转 MyBatis：深度解析与定制-LinkedBear-掘金小册</a></li>
<li><a target="_blank" rel="noopener" href="https://snailclimb.gitee.io/javaguide-interview/#/./docs/e-2mybatis">MyBatis (JavaGuide)</a></li>
<li><a target="_blank" rel="noopener" href="https://www.bilibili.com/video/BV1d4411g7tv?p=256">雷丰阳Spring、Spring MVC、MyBatis课程-bilibili</a></li>
</ul>
</article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">h0ss</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://blog.gpnusz.cn/2021/08/06/Mybatis%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/">https://blog.gpnusz.cn/2021/08/06/Mybatis%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://blog.gpnusz.cn" target="_blank">后端学习记录</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Mybatis/">Mybatis</a></div><div class="post_share"></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2022/01/21/%E3%80%90%E5%8A%9B%E6%89%A3%E9%A2%98%E8%A7%A3%E3%80%91%E7%9F%B3%E5%AD%90%E6%B8%B8%E6%88%8F-IX/"><img class="prev-cover" src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1af54aa0fd9f4eb6bc6f38efbd2afcc7~tplv-k3u1fbpfcp-watermark.image" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">【力扣题解】石子游戏 IX</div></div></a></div><div class="next-post pull-right"><a href="/2021/08/01/SpringMVC%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"><img class="next-cover" src="https://static01.imgkr.com/temp/07cc3f2f859f40ef8733044657da8465.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">SpringMVC学习笔记</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="card-info-avatar is-center"><img class="avatar-img" src="/img/avatar.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/><div class="author-info__name">h0ss</div><div class="author-info__description">一个苦逼后端仔的学习记录</div></div><div class="card-info-data"><div class="card-info-data-item is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">51</div></a></div><div class="card-info-data-item is-center"><a href="/tags/"><div class="headline">标签</div><div class="length-num">14</div></a></div></div><a class="button--animated" id="card-info-btn" target="_blank" rel="noopener" href="https://gitee.com/h0ss"><i class="fab fa-github"></i><span>Gitee仓库</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn card-announcement-animation"></i><span>公告</span></div><div class="announcement_content">Java后端技术栈语雀文档：https://www.yuque.com/oliver-wdtb1/java</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2022/11/16/%E7%BB%99%E5%BC%80%E6%BA%90%E9%A1%B9%E7%9B%AE%E6%8F%90%E4%BA%86%E4%B8%AAPR/" title="给开源项目提了个PR">给开源项目提了个PR</a><time datetime="2022-11-15T17:28:40.000Z" title="发表于 2022-11-16 01:28:40">2022-11-16</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2022/09/03/%E3%80%90MySQL%E3%80%91InnoDB%E7%9A%84%E8%A1%8C%E6%A0%BC%E5%BC%8F/" title="【MySQL】InnoDB的行格式">【MySQL】InnoDB的行格式</a><time datetime="2022-09-02T18:17:38.000Z" title="发表于 2022-09-03 02:17:38">2022-09-03</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2022/08/21/%E3%80%90Debug%E3%80%91bitField-%E5%BC%95%E5%8F%91%E7%9A%84%E6%A0%88%E6%BA%A2%E5%87%BA%E6%8E%92%E9%94%99%E8%AE%B0/" title="【Debug】bitField 引发的栈溢出排错记">【Debug】bitField 引发的栈溢出排错记</a><time datetime="2022-08-20T18:10:40.000Z" title="发表于 2022-08-21 02:10:40">2022-08-21</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2022/07/16/%E3%80%90RPC%E3%80%91%E8%AF%A6%E8%A7%A3SPI%E6%9C%BA%E5%88%B6/" title="【RPC】详解SPI机制">【RPC】详解SPI机制</a><time datetime="2022-07-15T18:51:57.000Z" title="发表于 2022-07-16 02:51:57">2022-07-16</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2022/07/14/%E3%80%90Redis%E3%80%91%E9%87%8D%E8%A6%81%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%9F%BA%E7%A1%80/" title="【Redis】重要数据结构基础">【Redis】重要数据结构基础</a><time datetime="2022-07-13T17:22:08.000Z" title="发表于 2022-07-14 01:22:08">2022-07-14</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><div class="js-pjax"></div><script defer="defer" id="fluttering_ribbon" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-fluttering-ribbon.min.js"></script><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="99" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js"></script><script id="click-heart" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js" async="async" mobile="false"></script><script id="click-show-text" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-show-text.min.js" data-mobile="false" data-text="爱国,敬业,诚信,友善,自由,平等,公正,法治,富强,民主,文明,和谐" data-fontsize="16px" data-random="false" async="async"></script></div></body></html>